//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

#include "LeakyBucketProfiler.h"

Define_Module(LeakyBucketProfiler)

void LeakyBucketProfiler::initialize(){
	AbstractProfiler::initialize();
	byteFlow = par("byteFlow");
	currentByteFlow = byteFlow;
	lastFlowIncrement = SIMTIME_ZERO;
	lastDelayedPacket = NULL;
}

bool LeakyBucketProfiler::acceptPacket(NetPacket* packet, simtime_t& delay){
	simtime_t currentTime = simTime();
	simtime_t timeDiff = currentTime - lastFlowIncrement;

	if(timeDiff > 0)
		currentByteFlow = std::min((int32_t)(currentByteFlow + byteFlow * timeDiff.dbl()), byteFlow);
	lastFlowIncrement = currentTime;

	// Zakladajac ze obliczenia dla ostatniego zakolejkowanego pakietu sa
	// poprawne mozemy bezproblemowo przeslac go dalej.
	if(packet == lastDelayedPacket)
		return true;
	else if(packet->getByteLength() <= currentByteFlow)
	{
		// Jesli dlugosc pakietu jest niewieksza od liczby tokenow to mozna go
		// przeslac dalej.
		currentByteFlow -= packet->getByteLength();
		return true;
	}
	else
	{
		// Wylicz czas po ktorym ma nastapic kolejne sprawdzenie dla tego pakietu.
		lastDelayedPacket = packet;
		delay = (double)(packet->getByteLength() - currentByteFlow) / byteFlow;
		currentByteFlow -= packet->getByteLength(); // Mozliwe wartosci ujemne, ale jest to akceptowalne

		return false;
	}
}
